/**
* \file		TabComp.c
* \brief	Code des fonctions du module TabComp
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		TabComp.
*/

#include "TabComp.h"
#include <assert.h>

/*======================== Gestion de la mémoire =======================*/

void initTabComp(TabComp *ptabComp, int nb)
{
   int i;

   setNbCompTabComp(ptabComp, nb);
   ptabComp->tab = (Comportement **)malloc(nb *sizeof(Comportement*));

   for(i=0; i<nb; i++)
	{
	   setIemeCompTabComp(ptabComp, NULL, i);
	}
}

void creerTabComp(TabComp **ptabComp, int nb)
{
   *ptabComp = (TabComp *)malloc(sizeof(TabComp));
   initTabComp(*ptabComp, nb);
}

void libereTabComp(TabComp *ptabComp)
{
   int nb = getNbCompTabComp(ptabComp);
   int i;

   if(0 < nb)
	{
	   for(i=0; i<(nb); i++)
		{
		   detruireComp(getIemeCompTabComp(ptabComp, i));
		}

	   free(ptabComp->tab);
	   setNbCompTabComp(ptabComp, 0);
	   ptabComp->tab = NULL;
	}
}

void detruireTabComp(TabComp *ptabComp)
{
   libereTabComp(ptabComp);
   free(ptabComp);
}


/*============================= Accesseurs =============================*/

int getNbCompTabComp(const TabComp *ptabComp)
{
   return ptabComp->nbComp;
}

Comportement *getIemeCompTabComp(const TabComp *ptabComp, int i)
{
   /* Vérification : i est-il valide ? */
   assert(i <= getNbCompTabComp(ptabComp));
   assert(i >= 0);

   return ptabComp->tab[i];
}


/*============================== Mutateurs =============================*/

void setNbCompTabComp(TabComp *ptabComp, int nouvVal)
{
   ptabComp->nbComp = nouvVal;
}

void setIemeCompTabComp(TabComp *ptabComp, Comportement *pcomp, int i)
{
   assert(i <= getNbCompTabComp(ptabComp));
   assert(i >= 0);
   ptabComp->tab[i] = pcomp;
}


/*========================== Fonctions autres ==========================*/
/**
* \brief	Crée le tableau des Comportements tel qu'il sera utilisé dans
*		le jeu, en se basant sur les actions et en montant les listes
*		comportementales.
* \param	ptabComp	Pointeur vers un TabComp
*/
TabComp *creerDonneeTabComp()
{
   TabComp *ptabComp;
   Comportement *compTemp;
   Action *actTemp;

   char *nomComp, *nomAct;
   char *repres;
   int nb = 3;
   int noCase = 0;

   /* Initialisation du tableau */
   creerTabComp(&ptabComp, nb);

 /*========= Inactivité =========*/

   /* Création du comportement */
   nomComp = "Inactif";
   compTemp = creerCompletComp(nomComp);

   /* Création de la première action : récolte */
   nomAct = "Inactif";
   repres = "Inactif";

   actTemp = creerCompleteAction(nomAct, repres, inactif);
   ajouteActionComp(compTemp, actTemp);

   /* Ajout de la nouvelle compétence au tableau */
   setIemeCompTabComp(ptabComp, compTemp, noCase);

   noCase++;

 /*========= Ramassage du bois =========*/

   /* Création du comportement */
   nomComp = "RamBois";
   compTemp = creerCompletComp(nomComp);

   /* Création de la seconde action : fin de récolte */
   nomAct = "FinRecBois";
   repres = "FinRecBois";

   actTemp = creerCompleteAction(nomAct, repres, finRecolteBois);
   ajouteActionComp(compTemp, actTemp);

   /* Création de la première action : récolte */
   nomAct = "RecBois";
   repres = "RecBois";

   actTemp = creerCompleteAction(nomAct, repres, recolteBois);
   ajouteActionComp(compTemp, actTemp);

   /* Ajout de la nouvelle compétence au tableau */
   setIemeCompTabComp(ptabComp, compTemp, noCase);

   noCase++;

 /*========= Ramassage du métal =========*/

   /* Création du comportement */
   nomComp = "RamMetal";
   compTemp = creerCompletComp(nomComp);

   /* Création de la seconde action : fin de récolte */
   nomAct = "FinRecMetal";
   repres = "FinRecMetal";

   actTemp = creerCompleteAction(nomAct, repres, finRecolteMetal);
   ajouteActionComp(compTemp, actTemp);

   /* Création de la première action : récolte */
   nomAct = "RecMetal";
   repres = "RecMetal";

   actTemp = creerCompleteAction(nomAct, repres, recolteMetal);
   ajouteActionComp(compTemp, actTemp);

   /* Ajout de la nouvelle compétence au tableau */
   setIemeCompTabComp(ptabComp, compTemp, noCase);

   return ptabComp;
}

Comportement *rechercheCompNomTabComp(TabComp *ptabComp, char *nomComp)
{
   int nb = getNbCompTabComp(ptabComp);
   int i;

   /* Si le comportement existe, le retourner */
   for(i=0; i<nb; i++)
	{
	   if(1 == compareNomComp(getIemeCompTabComp(ptabComp, i), nomComp))
		{
		   return getIemeCompTabComp(ptabComp, i);
		}
	}

   /* Sinon, retourner le comportement inactif (par convention, le premier
   comportement du tableau) */
   return getIemeCompTabComp(ptabComp, 0);

}

/**
* \brief	Renvoie le comportement associé à la production dont on aura
*		donné le nom en paramètre. Si aucun comportement ne convient,
*		renvoie le comportement Inactif.
* \param	ptabComp	Pointeur vers un TabComp
* \param	nomProd		Nom de la production
*/
Comportement *rechercherCompNomProdTabComp(TabComp *ptabComp, char *nomProd)
{

   if(0 == strcmp(nomProd, "bois"))
	{
	   return rechercheCompNomTabComp(ptabComp, "RamBois");
	}
   else
	{
	   if (0 == strcmp(nomProd, "metal"))
		{
		   return rechercheCompNomTabComp(ptabComp, "RamMetal");
		}

	   else
		{
		   return rechercheCompNomTabComp(ptabComp, "Inactif");
		}
	}

}

/*========================== Fonction de Test ==========================*/

void testTabComp()
{
   TabComp *ptabComp;
   int nb, i;
   Comportement *compTest;

   printf("Test de TabComp\n");
   printf("\tInitialisation d'un TabComp\t\t\t");
   nb = 6;
   creerTabComp(&ptabComp, nb);

   assert(nb == getNbCompTabComp(ptabComp));
 
   for (i=0; i<6; i++)
	{
	   assert(NULL == getIemeCompTabComp(ptabComp,i));
	}

   printf("OK\n");


   detruireTabComp(ptabComp);


   printf("\tCréation du tableau de données\n");
   ptabComp = creerDonneeTabComp();

   printf("\t\tNom des comportements implémentés\n");
   nb = getNbCompTabComp(ptabComp);

   for(i=0; i<nb; i++)
	{
	   printf("\t\t\t%s\n", getNomComp(getIemeCompTabComp(ptabComp, i)));
	}

   printf("\tRecherche de comportement dans le tableau\n");
   printf("\t\tComportement y figurant : RamBois\n");
   compTest = rechercheCompNomTabComp(ptabComp, "RamBois");
   printf("\t\tComportement renvoyé : %s\n", getNomComp(compTest));
   printf("\t\tComportement n'y figurant pas : Attaque\n");
   compTest = rechercheCompNomTabComp(ptabComp, "Attaque");
   printf("\t\tComportement renvoyé : %s\n", getNomComp(compTest));

   printf("\tAssociation d'un comportement à une production\n");
   compTest = rechercherCompNomProdTabComp(ptabComp, "bois");
   printf("\t\tProduction donnée : bois, Comportement renvoyé : %s\n", getNomComp(compTest));
   compTest = rechercherCompNomProdTabComp(ptabComp, "metal");
   printf("\t\tProduction donnée : metal, Comportement renvoyé : %s\n", getNomComp(compTest));
   compTest = rechercherCompNomProdTabComp(ptabComp, "fanfreluches");
   printf("\t\tProduction donnée : fanfreluches, Comportement renvoyé : %s\n", getNomComp(compTest));


   printf("\n");

   detruireTabComp(ptabComp);
}
